import Vue from 'vue'
import store from '@/store'

/**
 * opt  object | string
 * to_url object | string
 * 例:
 * this.Tips('/pages/test/test'); 跳转不提示
 * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转
 * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上
 * tab=1 一定时间后跳转至 table上
 * tab=2 一定时间后跳转至非 table上
 * tab=3 一定时间后返回上页面
 * tab=4 关闭所有页面，打开到应用内的某个页面
 * tab=5 关闭当前页面，跳转到应用内的某个页面
 */
const Tips = function(opt, to_url) {
	if (typeof opt == 'string') {
		to_url = opt;
		opt = {};
	}
	let title = opt.title || '',
		icon = opt.icon || 'none',
		endtime = opt.endtime || 2000,
		success = opt.success;
	if (title) uni.showToast({
		title: title,
		icon: icon,
		duration: endtime,
		success
	})
	if (to_url != undefined) {
		if (typeof to_url == 'object') {
			let tab = to_url.tab || 1,
				url = to_url.url || '';
			switch (tab) {
				case 1:
					//一定时间后跳转至 table
					setTimeout(function() {
						uni.navigateTo({
							url: url
						})
					}, endtime);
					break;
				case 2:
					//跳转至非table页面
					setTimeout(function() {
						uni.navigateTo({
							url: url,
						})
					}, endtime);
					break;
				case 3:
					//返回上页面
					setTimeout(function() {
						// #ifndef H5
						uni.navigateBack({
							delta: parseInt(url),
						})
						// #endif
						// #ifdef H5
						history.back();
						// #endif
					}, endtime);
					break;
				case 4:
					//关闭所有页面，打开到应用内的某个页面
					setTimeout(function() {
						uni.reLaunch({
							url: url,
						})
					}, endtime);
					break;
				case 5:
					//关闭当前页面，跳转到应用内的某个页面
					setTimeout(function() {
						uni.redirectTo({
							url: url,
						})
					}, endtime);
					break;
				case 6:
					// 跳转到 tabBar 页面，并关闭其他所有非 tabBar 页面
					setTimeout(function() {
						uni.switchTab({
							url: url,
						})
					}, endtime);
					break;
			}

		} else if (typeof to_url == 'function') {
			setTimeout(function() {
				to_url && to_url();
			}, endtime);
		} else {
			//没有提示时跳转不延迟
			setTimeout(function() {
				uni.navigateTo({
					url: to_url,
				})
			}, title ? endtime : 0);
		}
	}
}
/**
 * 跳转路径封装函数
 * @param url 跳转路径
 * 选择跳转到其他小程序时，在h5也可以跳转路径
 */
const JumpPath = (url) => {
	let arr = url.split('@APPID=');
	let index = url.indexOf('@KSSEVENT')

	if (arr.length > 1) {
		//#ifdef MP
		uni.navigateToMiniProgram({
			appId: arr[arr.length - 1], // 此为生活缴费appid
			path: arr[0], // 此为生活缴费首页路径
			envVersion: "release",
			success: res => {
				console.log("打开小程序成功", res);
			},
			fail: err => {
				console.log('打开小程序失败', err);
			}
		})
		//#endif
		//#ifndef MP
		Tips({
			title: 'h5与app端不支持跳转外部小程序'
		});
		//#endif
	} else if (index != -1) {
		// 事件
		let match = url.match(/(\S*)+@KSSEVENT(\S*)+/i)
		const event_name = match[0]
		const event_params = match[1].replace('=', '')
		switch (event_name) {
			case 'logout':
				Vue.prototype.$u.api.logout()
				store.dispatch('logout')
				/* #ifdef H5 */
				location.reload()
				/* #endif */
				break;
			default:
				break;
		}
	} else {
		if (url.indexOf("http") != -1) {
			// #ifdef H5
			location.href = url;
			// #endif
			// #ifdef MP || APP-PLUS
			uni.navigateTo({
				url: `/pages/common/webview?url=${url}`
			});
			// #endif
		} else {
			if (store.getters['app/tabBarNavList'].indexOf(
					url) == -1) {
				uni.navigateTo({
					url
				})
			} else {
				uni.switchTab({
					url
				})
			}
		}
	}
}
/**
 * 小程序比较版本信息
 * @param v1 当前版本
 * @param v2 进行比较的版本 
 * @return boolen
 * 
 */
const compareVersion = (v1, v2) => {
	v1 = v1.split('.')
	v2 = v2.split('.')
	const len = Math.max(v1.length, v2.length)

	while (v1.length < len) {
		v1.push('0')
	}
	while (v2.length < len) {
		v2.push('0')
	}

	for (let i = 0; i < len; i++) {
		const num1 = parseInt(v1[i])
		const num2 = parseInt(v2[i])

		if (num1 > num2) {
			return 1
		} else if (num1 < num2) {
			return -1
		}
	}

	return 0
}
const $h = {
	//除法函数，用来得到精确的除法结果
	//说明：javascript的除法结果会有误差，在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
	//调用：$h.Div(arg1,arg2)
	//返回值：arg1除以arg2的精确结果
	Div: function(arg1, arg2) {
		arg1 = parseFloat(arg1);
		arg2 = parseFloat(arg2);
		var t1 = 0,
			t2 = 0,
			r1, r2;
		try {
			t1 = arg1.toString().split(".")[1].length;
		} catch (e) {}
		try {
			t2 = arg2.toString().split(".")[1].length;
		} catch (e) {}
		r1 = Number(arg1.toString().replace(".", ""));
		r2 = Number(arg2.toString().replace(".", ""));
		return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
	},
	//加法函数，用来得到精确的加法结果
	//说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
	//调用：$h.Add(arg1,arg2)
	//返回值：arg1加上arg2的精确结果
	Add: function(arg1, arg2) {
		arg2 = parseFloat(arg2);
		var r1, r2, m;
		try {
			r1 = arg1.toString().split(".")[1].length
		} catch (e) {
			r1 = 0
		}
		try {
			r2 = arg2.toString().split(".")[1].length
		} catch (e) {
			r2 = 0
		}
		m = Math.pow(100, Math.max(r1, r2));
		return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
	},
	//减法函数，用来得到精确的减法结果
	//说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
	//调用：$h.Sub(arg1,arg2)
	//返回值：arg1减去arg2的精确结果
	Sub: function(arg1, arg2) {
		arg1 = parseFloat(arg1);
		arg2 = parseFloat(arg2);
		var r1, r2, m, n;
		try {
			r1 = arg1.toString().split(".")[1].length
		} catch (e) {
			r1 = 0
		}
		try {
			r2 = arg2.toString().split(".")[1].length
		} catch (e) {
			r2 = 0
		}
		m = Math.pow(10, Math.max(r1, r2));
		//动态控制精度长度
		n = (r1 >= r2) ? r1 : r2;
		return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
	},
	//乘法函数，用来得到精确的乘法结果
	//说明：javascript的乘法结果会有误差，在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
	//调用：$h.Mul(arg1,arg2)
	//返回值：arg1乘以arg2的精确结果
	Mul: function(arg1, arg2) {
		arg1 = parseFloat(arg1);
		arg2 = parseFloat(arg2);
		var m = 0,
			s1 = arg1.toString(),
			s2 = arg2.toString();
		try {
			m += s1.split(".")[1].length
		} catch (e) {}
		try {
			m += s2.split(".")[1].length
		} catch (e) {}
		return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
	},
}
// 获取地理位置;
const $L = {
	async getLocation() {
		// #ifdef APP-PLUS
		let status = await this.checkPermission();
		if (status !== 1) {
			return;
		}
		// #endif
		// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
		let status = await this.getSetting();
		if (status === 2) {
			this.openSetting();
			return;
		}
		// #endif

		this.doGetLocation();
	},
	doGetLocation() {
		uni.getLocation({
			success: (res) => {
				uni.removeStorageSync('CACHE_LONGITUDE');
				uni.removeStorageSync('CACHE_LATITUDE');
				uni.setStorageSync('CACHE_LONGITUDE', res.longitude);
				uni.setStorageSync('CACHE_LATITUDE', res.latitude);
			},
			fail: (err) => {
				// #ifdef MP-BAIDU
				if (err.errCode === 202 || err.errCode === 10003) { // 202模拟器 10003真机 user deny
					this.openSetting();
				}
				// #endif
				// #ifndef MP-BAIDU
				if (err.errMsg.indexOf("auth deny") >= 0) {
					uni.showToast({
						title: "访问位置被拒绝"
					})
				} else {
					uni.showToast({
						title: err.errMsg
					})
				}
				// #endif
			}
		})
	},
	getSetting: function() {
		return new Promise((resolve, reject) => {
			uni.getSetting({
				success: (res) => {
					if (res.authSetting['scope.userLocation'] === undefined) {
						resolve(0);
						return;
					}
					if (res.authSetting['scope.userLocation']) {
						resolve(1);
					} else {
						resolve(2);
					}
				}
			});
		});
	},
	openSetting: function() {
		uni.openSetting({
			success: (res) => {
				if (res.authSetting && res.authSetting['scope.userLocation']) {
					this.doGetLocation();
				}
			},
			fail: (err) => {}
		})
	},
	async checkPermission() {
		let status = permision.isIOS ? await permision.requestIOS('location') :
			await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');

		if (status === null || status === 1) {
			status = 1;
		} else if (status === 2) {
			uni.showModal({
				content: "系统定位已关闭",
				confirmText: "确定",
				showCancel: false,
				success: function(res) {}
			})
		} else if (status.code) {
			uni.showModal({
				content: status.message
			})
		} else {
			uni.showModal({
				content: "需要定位权限",
				confirmText: "设置",
				success: function(res) {
					if (res.confirm) {
						permision.gotoAppSetting();
					}
				}
			})
		}
		return status;
	},
}

// promise封装storage
const MyLocalStorage = {
	setStorage: (key, data, callback = undefined) => {
		return new Promise((resolve, reject) => {
			uni.setStorage({
				key,
				data,
				success: function() {
					resolve()
				},
				fail: function(e) {
					reject(e)
				},
				complete: function() {
					if (callback)
						callback()
				}
			})
		})
	},
	getStorage: (key, callback = undefined) => {
		return new Promise((resolve, reject) => {
			uni.getStorage({
				key,
				success: function(res) {
					resolve(res.data)
				},
				fail: function(e) {
					reject(e)
				},
				complete: function() {
					if (callback)
						callback()
				}
			})
		})
	},
	removeStorage: (key, callback = undefined) => {
		return new Promise((resolve, reject) => {
			uni.removeStorage({
				key,
				success: function(res) {
					resolve(res.data)
				},
				fail: function(e) {
					reject(e)
				},
				complete: function() {
					if (callback)
						callback()
				}
			})
		})
	},
	clearStorage: (callback = undefined) => {
		return new Promise((resolve, reject) => {
			try {
				uni.clearStorageSync()
				resolve()
			} catch (e) {
				reject(e)
			} finally {
				if (callback)
					callback()
			}
		})
	},
}
/**
 * 手机号码脱敏处理
 * @param {String} phone 手机号码
 * @returns {String} 脱敏后的手机号码
 */
const maskPhone = (phone) => {
	if (!phone || typeof phone !== 'string' || phone.length !== 11) {
		return phone
	}
	return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}

const getRedirectUrl = (path, query) => {
	let query_str = []
	for (let i in query)
		query_str.push(`${i}=${query[i]}`)
	if (query_str.length)
		return `${path}?${query_str.join('&')}`
	else
		return path
}

const install = Vue => {
	Vue.prototype.$util = {
		Tips,
		JumpPath,
		compareVersion,
		$h,
		$L,
		MyLocalStorage,
		maskPhone,
		getRedirectUrl,
	}

}


export default {
	install
}